<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>05_components_composing</title>
</head>
<body>

<div id="example"></div>

<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
    /*
        问题：数据保存在那个组件内？
            看数据是某个组件需要(给它)，还是某些组件需要（共同的父组件）
        问题2：需要在子组件中改变父组件的状态
            子组件中不能直接改变父组件的转态
            状态在哪个组件，更新转态的行为就应该定义在哪个组件中

            解决：父组件定义函数，传递给子组件，子组件调用


        组件化编写功能的流程：
            1. 拆分组件
            2. 实现静态组件（只有静态页面，没有动态数据和交互）
            3. 实现动态组件
                1) 实现初始化数据动态显示
                2) 实现交互功能

        设计思路：一个页面就是一个app，app里面且套组件

     */

    // 创建组件
    class Counter extends React.Component {
        constructor(props) {
            super(props);

            // 初始化转态
            const todos = ["吃饭", "睡觉", "挤痘痘"];
            const count = todos.length + 1;
            this.state = {todos, count}

            // 修改自定义方法设置 this
            this.addTodo = this.addTodo.bind(this);
        }

        addTodo(todo) {
            // 更新后的值
            const {todos} = this.state;
            todos.unshift(todo);
            // 设置值
            this.setState({todos})
        }

        render() {
            const {todos,count} = this.state;
            return (
                <div>
                    <Add count={count} addTodo={this.addTodo}/>
                    <List todos={todos}/>
                </div>
            )
        }
    }

    class Add extends React.Component {
        constructor(props) {
            super(props);

            // 设置自定义方法的this
            this.add = this.add.bind(this);
        }

        render() {
            const {count} = this.props;
            return (
                <div>
                    <input type="text" ref={(input) => this.input = input}/> &nbsp; &nbsp;
                    <button onClick={this.add}>添加#{count + 1}</button>
                </div>
            )
        }

        add() {
            // 获取填充值
            const todo = this.input.value.trim();
            console.log(todo);
            // 校验合法性
            if (!todo) {
                return
            }
            // 添加到列表中（子组件只能调用父组件的方法，来改变父组件的转态）
            this.props.addTodo(todo);
            // 置空
            this.input.value = "";
        }
    }

    Add.propTypes = {
        count: PropTypes.number.isRequired,
        addTodo: PropTypes.func.isRequired
    }

    class List extends React.Component {
        render() {

            return (
                <div>
                    <ul>
                        {this.props.todos.map((value, index) => <li key={index}>{value}</li>)}
                    </ul>
                </div>
            )
        }
    }

    // 设置参数的类型
    List.propTypes = {
        todos: PropTypes.array.isRequired
    }


    // 渲染组件
    ReactDOM.render(<Counter/>, document.getElementById("example"));
</script>